﻿using Vision001.Models;
using Vision001.Procedure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Vision001.Helper
{
    /// <summary>
    /// 测试方法帮助类
    /// </summary>
    public static class TestMethodHelper
    {
        /// <summary>
        /// 加载所有测试方法
        /// </summary>
        public static Task LoadAllMethods()
        {
            return Task.Run(() =>
            {
                try
                {
                    //加载所有设置方法
                    Global.TestSetMethodModelActions = GetSetStaticMethods<TestMethodModel>(typeof(TestMethod));
                    //加载所有读取方法
                    Global.TestGetMethodModelActions = GetGetStaticMethods<TestMethodModel>(typeof(TestMethod));
                }
                catch (Exception e)
                {
                    throw e;
                }
            });
        }

        /// <summary>
        /// 执行所有测试方法
        /// </summary>
        public static void StartAutoTest()
        {
            //自动按照测试流程执行
            //解析测试流程
            try
            {
                var result = Global._TestProcedureConfigs.Where(p => p.type == ProcessType.读取方法 && p.IsRun == "1")
                    .OrderBy(s => s.ExecutionSequence).ToList();

                for (int i = 0; i < result.Count; i++)
                {
                    //拿到每一个读取方法对应的前置设置方法
                    var BeforCondition = Global._TestProcedureConfigs.Where(p => p.TargetProcess == result[i].ProcessName && p.TestCondition == "前置" && p.Group == result[i].Group && p.IsRun == "1")
                        .OrderBy(s => s.ExecutionSequence).ToList();
                    //拿到每一个读取方法对应的后置设置方法
                    var NextCondition = Global._TestProcedureConfigs.Where(p => p.TargetProcess == result[i].ProcessName && p.TestCondition == "后置" && p.Group == result[i].Group && p.IsRun == "1")
                        .OrderBy(s => s.ExecutionSequence).ToList();

                    //先执行前置设置方法，再执行后置设置方法
                    if (BeforCondition.Count > 0)
                    {
                        for (int j = 0; j < BeforCondition.Count; j++)
                        {
                            Global.TestSetMethodModelActions[BeforCondition[j].ProcessName].Invoke(BeforCondition[j]);
                        }
                    }
                    //执行读取方法
                    Global.TestGetMethodModelActions[result[i].ProcessName].Invoke(result[i]);
                    //执行后置设置方法
                    if (NextCondition.Count > 0)
                    {
                        for (int k = 0; k < NextCondition.Count; k++)
                        {
                            Global.TestSetMethodModelActions[NextCondition[k].ProcessName].Invoke(NextCondition[k]);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>
        /// 返回目标类里的所有静态无返回值方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="staticClassType"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static Dictionary<string, Action<T>> GetSetStaticMethods<T>(Type staticClassType)
        {
            if (!staticClassType.IsAbstract || !staticClassType.IsSealed)
                throw new ArgumentException("Type must be a static class");

            var methods = new Dictionary<string, Action<T>>();
            var targetParamType = typeof(T);

            foreach (var method in staticClassType.GetMethods(
                         BindingFlags.Public |
                         BindingFlags.Static |
                         BindingFlags.FlattenHierarchy))
            {
                var parameters = method.GetParameters();

                // 筛选条件：单参数且类型匹配，无返回值
                if (parameters.Length == 1 &&
                    parameters[0].ParameterType == targetParamType &&
                    method.ReturnType == typeof(void))
                {
                    var key = method.Name;
                    var value = (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), method);
                    methods.Add(key, value);
                }
            }

            return methods;
        }

        /// <summary>
        /// 返回目标类里的所有静态返回值为bool的方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="staticClassType"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static Dictionary<string, Func<T, bool>> GetGetStaticMethods<T>(Type staticClassType)
        {
            if (!staticClassType.IsAbstract || !staticClassType.IsSealed)
                throw new ArgumentException("Type must be a static class");

            var methods = new Dictionary<string, Func<T, bool>>();
            var targetParamType = typeof(T);

            foreach (var method in staticClassType.GetMethods(
                         BindingFlags.Public |
                         BindingFlags.Static |
                         BindingFlags.FlattenHierarchy))
            {
                var parameters = method.GetParameters();

                // 筛选条件：单参数且类型匹配，无返回值
                if (parameters.Length == 1 &&
                    parameters[0].ParameterType == targetParamType &&
                    method.ReturnType == typeof(bool))
                {
                    var key = method.Name;
                    var value = (Func<T, bool>)Delegate.CreateDelegate(typeof(Func<T, bool>), method);
                    methods.Add(key, value);
                }
            }

            return methods;
        }
    }
}